package com.iuie.ns.datum.service.impl;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.io.Serializable;
import java.net.URLEncoder;
import java.util.Date;

import javax.annotation.Resource;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;

import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.MediaType;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import com.iuie.ns.datum.service.IFileInfoService;
import com.iuie.ns.datum.service.IFileService;
import com.iuie.ns.datum.vo.FileInfoVO;
import com.iuie.ns.frame.config.AppConfigUtil;
import com.iuie.ns.frame.utils.StringUtils;

@Service("fileService")
@Transactional
public class FileServiceImpl implements IFileService{

	private static final Logger log = LoggerFactory.getLogger(FileInfoServiceImpl.class);
	
	public static final String BLOG_FILE_PATH = AppConfigUtil.getInstance().getProperty("blog.upload.path");
	
	public static final String FILE_PATH = AppConfigUtil.getInstance().getProperty("file.upload.path");
	
	@Resource
	private IFileInfoService fileInfoService;
	
	@Override
	public FileInfoVO addOneFile(MultipartFile file, Boolean immediately, String fileType) throws IOException {
		if(file.isEmpty()){
			throw new IOException("文件内容为空");
		}
		String originalName = file.getOriginalFilename();
		long fileSize = file.getSize();
		FileInfoVO fileInfo = new FileInfoVO();
		long fileId = System.currentTimeMillis();
		
		String fileName = null;
		if (immediately!=null && immediately==true) {
			// 立即保存-文件名为时间戳
			fileName = String.valueOf(fileId)+"."+FilenameUtils.getExtension(originalName);
		} else {
			// 非立即保存-文件名以"--"开头
			fileName = "--" + String.valueOf(fileId)+"." + FilenameUtils.getExtension(originalName);
		}
		
		fileInfo.setFileId(fileId);
		fileInfo.setOriginalName(originalName);
		fileInfo.setFileName(fileName);
		fileInfo.setUploadTime(new Date());
		fileInfo.setFileSize(fileSize);
		fileInfo.setFileType(fileType);
		
		fileInfoService.addOne(fileInfo);
		
		// fileType is blog or file
		String storePath = getPath(fileType);
		// 拷贝到E盘目录下
		if(!file.isEmpty()){
			log.debug("Process file:{}"+file.getOriginalFilename());
			FileUtils.copyInputStreamToFile(file.getInputStream(),
					new File(storePath,fileName));
		}
		return fileInfo;
	}

	@Override
	public void deleteFileById(Serializable fileId) {
		this.deleteFileById(fileId, false, "file");
	}
	
	@Override
	public void deleteFileById(Serializable fileId, boolean deleteTag, String fileType) {
		FileInfoVO fileInfo = fileInfoService.findById(fileId);
		String path = getPath(fileType);
		File f = new File(path,fileInfo.getFileName());
		boolean flag = f.delete();
		// 文件删除成功再删除文件信息
		if (flag || deleteTag) {
			fileInfoService.deleteById(fileId);
		}
	}
	
	/**
	 * 根据文件类型取路径
	 * @param fileType
	 * @return
	 * @date 2017年8月15日 下午3:31:50
	 */
	private String getPath(String fileType) {
	    if (StringUtils.equals(fileType, "blog")) {
	        return BLOG_FILE_PATH;
	    } else if (StringUtils.equals(fileType, "file")) {
	        return FILE_PATH;
	    }
	    return null;
	}

	@Deprecated
	@Override
	public ResponseEntity<byte[]> fileDownload(Serializable fileId,Boolean download) throws IOException {
		if(download==null){
			download=Boolean.TRUE;
		}
		FileInfoVO fileInfo = fileInfoService.findById(fileId);
		File f = new File(FILE_PATH, fileInfo.getFileName());
		if (f.exists()) {
			fileInfoService.downloadFileById(fileId);
		}
		
        String fileName=new String(fileInfo.getOriginalName().getBytes("UTF-8"),"iso-8859-1");//为了解决中文名称乱码问题
        HttpHeaders headers = new HttpHeaders();    
        if(download){
	        headers.setContentDispositionFormData("attachment", fileName);  
	        headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
        }
        byte[] buffer = FileUtils.readFileToByteArray(f);
        return new ResponseEntity<byte[]>(buffer,headers,HttpStatus.CREATED);
	}

	@Override
	public void fileDownload(Serializable fileId, Boolean download,HttpServletRequest req,
			HttpServletResponse resp) throws ServletException, IOException {
		if(download==null){
			download=Boolean.TRUE;
		}
		FileInfoVO fileInfo = fileInfoService.findById(fileId);
		if(fileInfo.getFileSize() <= 41943040l){
			// 小于40M时
			req.getRequestDispatcher("/fileDownload.do").forward(req, resp);
			return ;
		}
		File f = new File(FILE_PATH, fileInfo.getFileName());
		
		if (f.exists()) {
			fileInfoService.downloadFileById(fileId);
		}
		try {
			if(download){
		        String fileName=fileInfo.getOriginalName(); 
		        resp.setCharacterEncoding("utf-8");
		        resp.setContentType("application/octet-stream");
		        String fileNameUrl = URLEncoder.encode(fileName,"UTF-8");
		        resp.setHeader("Content-Disposition", "form-data; name=\"attachment\";filename=\""+ fileNameUrl+"\"");
	        }
			
			FileInputStream fis = new FileInputStream(f);
			
			OutputStream os = resp.getOutputStream();
			byte[] buffer = new byte[1024];
			int length;
			while((length = fis.read(buffer))>0){
				os.write(buffer, 0, length);
			}
			
			os.flush();
			os.close();
			fis.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	@Override
	public void letFileNameLegal(Serializable fileId) throws IOException {
		FileInfoVO fileInfo = fileInfoService.loadById(fileId);
		if (fileInfo == null) {
			throw new NullPointerException("系统中不能找到该文件的相关信息：fileId=" + fileId);
		}
		String fileName = fileInfo.getFileName();
		File oldFile = new File(BLOG_FILE_PATH,fileInfo.getFileName());
		if (!oldFile.exists()) {
			throw new IOException("系统找不到文件：fileName=" + fileName);
		}
		if(fileName!=null && fileName.startsWith("--")){
			fileName = fileName.substring(2);
		}
		File newFile = new File(BLOG_FILE_PATH,fileName);
		if (!oldFile.renameTo(newFile)) {
			throw new IOException("文件名修改失败：fileName=" + fileName);
		}
		fileInfo.setFileName(fileName);
		
	}

}
